#include <iostream>
using std::cout;
using std::endl;
//拷贝构造函数的调用时机
class Point{
public:
    Point(int x, int y)
    :_x(x)
    ,_y(y)
    {
        cout << "Point(int,int)" << endl;
    }

    Point(const Point & rhs)
    :_x(rhs._x)
    ,_y(rhs._y)
    {
        //rhs._x = 0;
        //rhs._y = 0;
        cout << "Point(const Point &)" << endl;
    }
    void print(){
        cout << "Point::print" << endl;
    }

private:
    int _x;
    int _y;


};

void test(){
    Point pt(1, 2);
    Point pt2 = pt;
}

//记忆口诀：有名称的一般是左值，可以取地址；
//没有名称的一般是右值，不可以取地址
//但是有例外，"hello"也没有名字，但是可以取地址
void test2(){
    //左值和右值
    int a = 10;
    double d = 10.0;
    Point pt(1, 2);
    cout << &a << endl;
    cout << &d << endl;
    cout << &pt << endl;
    //不能够取地址，那么便是右值
    // 1 Point(1, 2)
    cout << &1 << endl;
    cout << Point(1, 2) << endl;
    //但是有一个非常特殊的存在，字符串也是右值，可以取地址
    cout << &"hello" << endl;
}

void test3(){
    int a = 10;
    int & ref = a;
    //为什么呢？因为2的生命周期只有在这一行生效，执行完这行代码之后
    //2便可以被销毁，如果一个引用绑定到了一个已经销毁的变量，
    //究竟取到的是什么呢？
    int & ref2 = 2;//非const引用尝试去绑定右值

    Point pt(1, 2);
    Point & ref3 = pt;
    //执行下面这行代码会创建Point对象，执行完毕之后随即便可以销毁对象
    //一个引用绑定到了一个已经销毁的对象，取到的是什么呢？
    Point & ref4 = Point(3, 4);
    //尝试使用const引用来去绑定，这样可以延长右值的生命周期
    //Point(4,5)该临时对象的生命周期会延长到和ref5的生命周期保持一致
    const Point & ref5 = Point(4, 5);
}

void test4(){
    Point pt = Point(4, 5);

    //以下两种写法其实背后都是使用的是拷贝构造函数
    //你可以理解为是编译器背后帮我们做了一个优化转换机制
    Point pt2(Point(3, 4));
    Point pt3 = Point(3, 4);
}

int main()
{
    test();
    return 0;
}

